C:\learncpp>mkdir ruby_cpp
C:\learncpp>cd ruby_cpp
C:\learncpp\ruby_cpp>cucumber
You don't have a 'features' directory. Please create one to get started.
See http://cukes.info/ for more information.
C:\learncpp\ruby_cpp>
Create a directory called "features"
Create a feature description file in the "features" directory called rpncalc_basic_operations.feature:
rpncalc_basic_operations.feature
Feature: Basic Operations
Scenario Outline: Perform some of the basic operations
Given the input "<input>"
When the calculator performs "<operator>"
Then the result should be "<output>"
Examples:
| input | operator | output |
| 30 4 | + | 34 |
| 30 4 | - | 26 |
| 5 | ! | 120 |
| 4 6 | * | 24 |
| 8 2 | / | 4 |
| 1 | - | -1 |
| | + | 0 |
| 8 0 | / | <error> |
| | $%^unknown*&^ | <error> |
Run cucumber again, it will report missing steps. Copy those code examples;
You can implement step definitions for undefined steps with these snippets:
Given /^the input "([^"]*)"$/ do |arg1|
pending # express the regexp above with the code you wish you had
end
When /^the calculator performs "([^"]*)"$/ do |arg1|
pending # express the regexp above with the code you wish you had
end
Then /^the result should be "([^"]*)"$/ do |arg1|
pending # express the regexp above with the code you wish you had
end
If you want snippets in a different programming language, just make sure a file
with the appropriate file extension exists where cucumber looks for step definitions.
Under the features directory create a directory called step_definitions
In the step_definitions directory create a file called rpncalc_steps.rb
rpncalc_steps.rb
Given /^the input "([^"]*)"$/ do |arg1|
pending # express the regexp above with the code you wish you had
end
When /^the calculator performs "([^"]*)"$/ do |arg1|
pending # express the regexp above with the code you wish you had
end
Then /^the result should be "([^"]*)"$/ do |arg1|
pending # express the regexp above with the code you wish you had
end
Creating the basic glue code
Create a file in the top-level directory called extconf.rb:
require 'fixture_glue'
Given /^the input "([^"]*)"$/ do |arg1|
@calc = RpnCalcFixture.new
arg1.split(/ /).collect{|s| @calc.enter(s.to_i)}
end
When /^the calculator performs "([^"]*)"$/ do |arg1|
@calc.perform(arg1)
end
Then /^the result should be "([^"]*)"$/ do |arg1|
# this should call getX, but the real calc is not implemented
end
Re-run cucumber:
C:\learncpp\ruby_cpp>cucumber
Feature: Basic Operations
Scenario Outline: Perform some of the basic operations # features\rpncalc_basi
c_operations.feature:2
Given the input "<input>" # features/step_definit
ions/rpncalc_steps.rb:3
When the calculator performs "<operator>" # features/step_definit
ions/rpncalc_steps.rb:8
Then the result should be "<output>" # features/step_definit
ions/rpncalc_steps.rb:12
Examples:
| input | operator | output |
|Creating calc
Enter value: 30
Enter value: 4
Performing: +
30 4 | + | 34 |
|Creating calc
Enter value: 30
Enter value: 4
Performing: -
30 4 | - | 26 |
|Creating calc
Enter value: 5
Performing: !
5 | ! | 120 |
|Creating calc
Enter value: 4
Enter value: 6
Performing: *
4 6 | * | 24 |
|Creating calc
Enter value: 8
Enter value: 2
Performing: /
8 2 | / | 4 |
|Creating calc
Enter value: 1
Performing: -
1 | - |Deleting calc
Deleting calc
Deleting calc
Deleting calc
Deleting calc
-1 |
|Creating calc
Performing: +
| + | 0 |
|Creating calc
Enter value: 8
Enter value: 0
Performing: /
8 0 | / | <error> |
|Creating calc
Performing: $%^unknown*&^
| $%^unknown*&^ | <error> |
9 scenarios (9 passed)
27 steps (27 passed)
0m0.031s
Deleting calc
Deleting calc
Deleting calc
Deleting calc
Preliminary Setup
Starting with Cucumber
- Create a directory called "features"
- Create a feature description file in the "features" directory called rpncalc_basic_operations.feature:
rpncalc_basic_operations.feature- Under the features directory create a directory called step_definitions
- In the step_definitions directory create a file called rpncalc_steps.rb
rpncalc_steps.rbCreating the basic glue code
- Create a file in the top-level directory called extconf.rb:
extconf.rbrequire 'mkmf' dir_config("fixture_glue") create_makefile("fixture_glue")- Create a file called fixture_glue.cpp:
fixture_glue.cpp#include "ruby.h" using namespace std; #include <stdio.h> VALUE cRpnCalcFixture; class RpnCalc { // this will actually be a production-class linked in // from a dynamic or static library (later) }; void RpnCalcFixture_Dispose(void *c) { printf("Deleting calc\n"); delete static_cast<RpnCalc*>(c); } VALUE RpnCalcFixture_New(VALUE clazz) { printf("Creating calc\n"); RpnCalc *c = new RpnCalc; VALUE tdata = Data_Wrap_Struct(clazz, 0, RpnCalcFixture_Dispose, c); rb_obj_call_init(tdata, 0, 0); return tdata; } VALUE RpnCalcFixture_Enter(VALUE self, VALUE value) { printf("Enter value: %d\n", NUM2INT(value)); return Qnil; } VALUE RpnCalcFixture_Perform(VALUE self, VALUE operatorName) { printf("Performing: %s\n", RSTRING_PTR(operatorName)); return Qnil; } VALUE RpnCalcFixture_X(VALUE self) { printf("Getting x\n"); return INT2NUM(12); } extern "C" { typedef VALUE(*V_F)(...); void Init_fixture_glue() { cRpnCalcFixture = rb_define_class("RpnCalcFixture", rb_cObject); rb_define_singleton_method( cRpnCalcFixture, "new", (V_F)RpnCalcFixture_New, 0); rb_define_method(cRpnCalcFixture, "x", (V_F)RpnCalcFixture_X, 0); rb_define_method(cRpnCalcFixture, "perform",(V_F)RpnCalcFixture_Perform, 1); rb_define_method(cRpnCalcFixture, "enter", (V_F)RpnCalcFixture_Enter, 1); } }Connecting to the glue code
require 'fixture_glue' Given /^the input "([^"]*)"$/ do |arg1| @calc = RpnCalcFixture.new arg1.split(/ /).collect{|s| @calc.enter(s.to_i)} end When /^the calculator performs "([^"]*)"$/ do |arg1| @calc.perform(arg1) end Then /^the result should be "([^"]*)"$/ do |arg1| # this should call getX, but the real calc is not implemented endC:\learncpp\ruby_cpp>cucumber Feature: Basic Operations Scenario Outline: Perform some of the basic operations # features\rpncalc_basi c_operations.feature:2 Given the input "<input>" # features/step_definit ions/rpncalc_steps.rb:3 When the calculator performs "<operator>" # features/step_definit ions/rpncalc_steps.rb:8 Then the result should be "<output>" # features/step_definit ions/rpncalc_steps.rb:12 Examples: | input | operator | output | |Creating calc Enter value: 30 Enter value: 4 Performing: + 30 4 | + | 34 | |Creating calc Enter value: 30 Enter value: 4 Performing: - 30 4 | - | 26 | |Creating calc Enter value: 5 Performing: ! 5 | ! | 120 | |Creating calc Enter value: 4 Enter value: 6 Performing: * 4 6 | * | 24 | |Creating calc Enter value: 8 Enter value: 2 Performing: / 8 2 | / | 4 | |Creating calc Enter value: 1 Performing: - 1 | - |Deleting calc Deleting calc Deleting calc Deleting calc Deleting calc -1 | |Creating calc Performing: + | + | 0 | |Creating calc Enter value: 8 Enter value: 0 Performing: / 8 0 | / | <error> | |Creating calc Performing: $%^unknown*&^ | $%^unknown*&^ | <error> | 9 scenarios (9 passed) 27 steps (27 passed) 0m0.031s Deleting calc Deleting calc Deleting calc Deleting calc<--Back